package com.kexio.user.service.impl;

import java.time.LocalDateTime;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kexio.auth.util.AuthContextUtils;
import com.kexio.user.dto.TenantDTO;
import com.kexio.user.entity.Tenant;
import com.kexio.user.mapper.TenantMapper;
import com.kexio.user.service.TenantService;

/**
 * 租户管理服务实现类
 * 
 * @author kexio
 * @since 1.0.0
 */
@Service
public class TenantServiceImpl implements TenantService {
    
    private static final Logger logger = LoggerFactory.getLogger(TenantServiceImpl.class);
    
    @Autowired
    private TenantMapper tenantMapper;

    // 使用Spring Cache + Redis分布式缓存
    
    @Override
    @Cacheable(cacheNames = "tenant:exists", key = "#tenantId", condition = "@tenantServiceImpl.isValidTenantIdFormat(#tenantId)")
    public boolean existsByTenantId(String tenantId) {
        try {
            if (!isValidTenantIdFormat(tenantId)) {
                return false;
            }

            int count = tenantMapper.countByTenantId(tenantId);
            boolean exists = count > 0;

            logger.debug("🔍 查询租户存在性 (分布式缓存): tenantId={}, exists={}", tenantId, exists);
            return exists;

        } catch (Exception e) {
            logger.error("查询租户存在性失败: tenantId={}, error={}", tenantId, e.getMessage());
            return false;
        }
    }

    @Override
    @Cacheable(cacheNames = "tenant:status", key = "#tenantId", condition = "@tenantServiceImpl.existsByTenantId(#tenantId)")
    public Integer getTenantStatus(String tenantId) {
        try {
            if (!existsByTenantId(tenantId)) {
                return null;
            }

            Integer status = tenantMapper.selectStatusByTenantId(tenantId);

            logger.debug("🔍 查询租户状态 (分布式缓存): tenantId={}, status={}", tenantId, status);
            return status;

        } catch (Exception e) {
            logger.error("查询租户状态失败: tenantId={}, error={}", tenantId, e.getMessage());
            return null;
        }
    }

    @Override
    public Tenant getTenantByTenantId(String tenantId) {
        try {
            if (!isValidTenantIdFormat(tenantId)) {
                return null;
            }

            Tenant tenant = tenantMapper.selectByTenantId(tenantId);

            logger.debug("查询租户信息: tenantId={}, found={}", tenantId, tenant != null);
            return tenant;

        } catch (Exception e) {
            logger.error("查询租户信息失败: tenantId={}, error={}", tenantId, e.getMessage());
            return null;
        }
    }

    @Override
    public int getUserCountByTenantId(String tenantId) {
        try {
            if (!existsByTenantId(tenantId)) {
                return 0;
            }

            int count = tenantMapper.countUsersByTenantId(tenantId);

            logger.debug("查询租户用户数量: tenantId={}, count={}", tenantId, count);
            return count;

        } catch (Exception e) {
            logger.error("查询租户用户数量失败: tenantId={}, error={}", tenantId, e.getMessage());
            return 0;
        }
    }

    @Override
    public boolean isValidTenant(String tenantId) {
        try {
            Integer status = getTenantStatus(tenantId);
            if (status == null) {
                return false;
            }

            // 状态为正常(1)或试用(2)的租户可以正常使用（可配置）
            boolean valid = status == 1 || status == 2;

            logger.debug("检查租户有效性: tenantId={}, status={}, valid={}", tenantId, status, valid);
            return valid;

        } catch (Exception e) {
            logger.error("检查租户有效性失败: tenantId={}, error={}", tenantId, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean isValidTenantIdFormat(String tenantId) {
        if (tenantId == null || tenantId.trim().isEmpty()) {
            return false;
        }

        // 租户ID规则：2-32位字符，只能包含字母、数字、下划线、连字符
        String pattern = "^[a-zA-Z0-9_-]{2,32}$";
        boolean valid = tenantId.matches(pattern);

        logger.debug("验证租户ID格式: tenantId={}, valid={}", tenantId, valid);
        return valid;
    }

    // ==================== CRUD 方法实现 ====================

    @Override
    @CacheEvict(cacheNames = "tenant:exists", key = "#request.tenantId", condition = "#request != null and #request.tenantId != null")
    public Tenant createTenant(TenantDTO request) {
        if (request == null) {
            throw new IllegalArgumentException("租户创建请求不能为空");
        }

        logger.info("创建租户开始: tenantId={}, tenantName={}",
            request.getTenantId(), request.getTenantName());

        // 1. 验证租户ID格式
        if (!isValidTenantIdFormat(request.getTenantId())) {
            throw new IllegalArgumentException("租户ID格式不正确");
        }

        // 2. 检查租户ID是否已存在
        if (existsByTenantId(request.getTenantId())) {
            throw new IllegalArgumentException("租户ID已存在: " + request.getTenantId());
        }

        // 3. 检查租户名称是否已存在
        if (existsByTenantName(request.getTenantName(), null)) {
            throw new IllegalArgumentException("租户名称已存在: " + request.getTenantName());
        }

        // 4. 转换DTO为实体
        Tenant tenant = request.toEntity();
        tenant.setCreateBy(AuthContextUtils.getCurrentUserId());
        tenant.setCreateTime(LocalDateTime.now());

        // 5. 保存到数据库
        tenantMapper.insert(tenant);


        logger.info("创建租户成功: id={}, tenantId={}", tenant.getId(), tenant.getTenantId());
        return tenant;
    }

    @Override
    public Tenant getTenantById(String id) {
        if (!StringUtils.hasText(id)) {
            return null;
        }

        try {
            Tenant tenant = tenantMapper.selectById(id);

            logger.debug("根据ID查询租户: id={}, found={}", id, tenant != null);
            return tenant;

        } catch (Exception e) {
            logger.error("根据ID查询租户失败: id={}, error={}", id, e.getMessage());
            return null;
        }
    }

    @Override
    @Caching(evict = {
        @CacheEvict(cacheNames = "tenant:exists", key = "#tenantId"),
        @CacheEvict(cacheNames = "tenant:status", key = "#tenantId")
    })
    public Tenant updateTenant(String tenantId, TenantDTO request) {
        if (!StringUtils.hasText(tenantId) || request == null) {
            throw new IllegalArgumentException("租户ID或更新请求不能为空");
        }

        logger.info("更新租户开始: tenantId={}, tenantName={}",
            tenantId, request.getTenantName());

        // 1. 查询现有租户
        Tenant existingTenant = getTenantByTenantId(tenantId);
        if (existingTenant == null) {
            throw new IllegalArgumentException("租户不存在: " + tenantId);
        }

        // 2. 检查租户名称是否重复（排除自己）
        if (StringUtils.hasText(request.getTenantName()) &&
            existsByTenantName(request.getTenantName(), tenantId)) {
            throw new IllegalArgumentException("租户名称已存在: " + request.getTenantName());
        }

        // 3. 更新字段
        if (StringUtils.hasText(request.getTenantName())) {
            existingTenant.setTenantName(request.getTenantName());
        }
        if (StringUtils.hasText(request.getTenantType())) {
            existingTenant.setTenantType(request.getTenantType());
        }
        if (request.getMaxUsers() != null) {
            existingTenant.setMaxUsers(request.getMaxUsers());
        }
        if (request.getExpireTime() != null) {
            existingTenant.setExpireTime(request.getExpireTime());
        }
        if (StringUtils.hasText(request.getContactName())) {
            existingTenant.setContactName(request.getContactName());
        }
        if (StringUtils.hasText(request.getContactPhone())) {
            existingTenant.setContactPhone(request.getContactPhone());
        }
        if (StringUtils.hasText(request.getContactEmail())) {
            existingTenant.setContactEmail(request.getContactEmail());
        }
        if (StringUtils.hasText(request.getDescription())) {
            existingTenant.setDescription(request.getDescription());
        }

        existingTenant.setUpdateBy(AuthContextUtils.getCurrentUserId());
        existingTenant.setUpdateTime(LocalDateTime.now());

        // 4. 保存更新
        tenantMapper.updateById(existingTenant);


        logger.info("更新租户成功: tenantId={}", tenantId);
        return existingTenant;
    }

    @Override
    @Caching(evict = {
        @CacheEvict(cacheNames = "tenant:exists", key = "#tenantId"),
        @CacheEvict(cacheNames = "tenant:status", key = "#tenantId")
    })
    public boolean deleteTenant(String tenantId) {
        if (!StringUtils.hasText(tenantId)) {
            throw new IllegalArgumentException("租户ID不能为空");
        }

        logger.info("删除租户开始: tenantId={}", tenantId);

        // 1. 检查租户是否存在
        if (!existsByTenantId(tenantId)) {
            throw new IllegalArgumentException("租户不存在: " + tenantId);
        }

        // 2. 检查租户下是否还有用户
        int userCount = getUserCountByTenantId(tenantId);
        if (userCount > 0) {
            throw new IllegalStateException("租户下还有 " + userCount + " 个用户，无法删除");
        }

        // 3. 执行软删除
        int deleted = tenantMapper.softDeleteTenant(tenantId,
            AuthContextUtils.getCurrentUserId(), LocalDateTime.now());


        boolean success = deleted > 0;
        logger.info("删除租户结果: tenantId={}, success={}", tenantId, success);
        return success;
    }

    @Override
    @CacheEvict(cacheNames = "tenant:status", key = "#tenantId")
    public boolean updateTenantStatus(String tenantId, Integer status) {
        if (!StringUtils.hasText(tenantId) || status == null) {
            throw new IllegalArgumentException("租户ID或状态不能为空");
        }

        // 验证状态值
        if (status < 0 || status > 4) {
            throw new IllegalArgumentException("无效的租户状态: " + status);
        }

        logger.info("更新租户状态开始: tenantId={}, status={}", tenantId, status);

        try {
            int updated = tenantMapper.updateTenantStatus(tenantId, status,
                AuthContextUtils.getCurrentUserId(), LocalDateTime.now());


            boolean success = updated > 0;
            logger.info("更新租户状态结果: tenantId={}, status={}, success={}",
                tenantId, status, success);
            return success;

        } catch (Exception e) {
            logger.error("更新租户状态失败: tenantId={}, status={}, error={}",
                tenantId, status, e.getMessage(), e);
            return false;
        }
    }

    // ==================== 分页查询方法实现 ====================

    @Override
    public Page<Tenant> getTenantPage(Long current, Long size) {
        return getTenantPage(current, size, null, null, null);
    }

    @Override
    public Page<Tenant> getTenantPage(Long current, Long size, String tenantName, Integer status, String tenantType) {
        try {
            Page<Tenant> page = new Page<>(current, size);

            LambdaQueryWrapper<Tenant> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Tenant::getDeleted, 0);

            // 条件筛选
            if (StringUtils.hasText(tenantName)) {
                queryWrapper.like(Tenant::getTenantName, tenantName);
            }
            if (status != null) {
                queryWrapper.eq(Tenant::getStatus, status);
            }
            if (StringUtils.hasText(tenantType)) {
                queryWrapper.eq(Tenant::getTenantType, tenantType);
            }

            // 排序：创建时间倒序
            queryWrapper.orderByDesc(Tenant::getCreateTime);

            Page<Tenant> result = tenantMapper.selectPage(page, queryWrapper);

            logger.debug("租户分页查询: current={}, size={}, total={}",
                current, size, result.getTotal());

            return result;

        } catch (Exception e) {
            logger.error("租户分页查询失败: error={}", e.getMessage(), e);
            return new Page<>(current, size);
        }
    }

    @Override
    public List<Tenant> getActiveTenants() {
        try {
            List<Tenant> tenants = tenantMapper.selectActiveTenants();

            logger.debug("查询活跃租户: count={}", tenants.size());
            return tenants;

        } catch (Exception e) {
            logger.error("查询活跃租户失败: error={}", e.getMessage(), e);
            return List.of();
        }
    }

    // ==================== 统计和验证方法实现 ====================

    @Override
    public boolean existsByTenantName(String tenantName, String excludeTenantId) {
        try {
            int count = tenantMapper.countByTenantName(tenantName, excludeTenantId);
            boolean exists = count > 0;

            logger.debug("检查租户名称存在性: tenantName={}, excludeTenantId={}, exists={}",
                tenantName, excludeTenantId, exists);
            return exists;

        } catch (Exception e) {
            logger.error("检查租户名称存在性失败: tenantName={}, error={}",
                tenantName, e.getMessage());
            return false;
        }
    }

    @Override
    public long getTotalTenantCount() {
        try {
            long count = tenantMapper.countTotalTenants();
            logger.debug("租户总数统计: count={}", count);
            return count;
        } catch (Exception e) {
            logger.error("租户总数统计失败: error={}", e.getMessage());
            return 0;
        }
    }

    @Override
    public long getActiveTenantCount() {
        try {
            long count = tenantMapper.countActiveTenants();
            logger.debug("活跃租户数统计: count={}", count);
            return count;
        } catch (Exception e) {
            logger.error("活跃租户数统计失败: error={}", e.getMessage());
            return 0;
        }
    }

    @Override
    public long getExpiringTenantCount(int days) {
        try {
            LocalDateTime expireTime = LocalDateTime.now().plusDays(days);
            long count = tenantMapper.countExpiringTenants(expireTime);

            logger.debug("即将过期租户统计: days={}, count={}", days, count);
            return count;
        } catch (Exception e) {
            logger.error("即将过期租户统计失败: days={}, error={}", days, e.getMessage());
            return 0;
        }
    }

    @Override
    public boolean canAddMoreUsers(String tenantId) {
        try {
            Tenant tenant = getTenantByTenantId(tenantId);
            if (tenant == null) {
                return false;
            }

            // 无限制
            if (tenant.getMaxUsers() == null || tenant.getMaxUsers() <= 0) {
                return true;
            }

            int currentUserCount = getUserCountByTenantId(tenantId);
            boolean canAdd = currentUserCount < tenant.getMaxUsers();

            logger.debug("检查用户配额: tenantId={}, current={}, max={}, canAdd={}",
                tenantId, currentUserCount, tenant.getMaxUsers(), canAdd);
            return canAdd;

        } catch (Exception e) {
            logger.error("检查用户配额失败: tenantId={}, error={}", tenantId, e.getMessage());
            return false;
        }
    }

    @Override
    public int getRemainingUserQuota(String tenantId) {
        try {
            Tenant tenant = getTenantByTenantId(tenantId);
            if (tenant == null) {
                return 0;
            }

            // 无限制
            if (tenant.getMaxUsers() == null || tenant.getMaxUsers() <= 0) {
                return -1;
            }

            int currentUserCount = getUserCountByTenantId(tenantId);
            int remaining = tenant.getMaxUsers() - currentUserCount;

            logger.debug("剩余用户配额: tenantId={}, current={}, max={}, remaining={}",
                tenantId, currentUserCount, tenant.getMaxUsers(), remaining);
            return Math.max(0, remaining);

        } catch (Exception e) {
            logger.error("查询剩余用户配额失败: tenantId={}, error={}", tenantId, e.getMessage());
            return 0;
        }
    }

    // ===== 内部租户验证工具方法 =====
    public boolean exists(String tenantId) { return existsByTenantId(tenantId); }
    public Integer getStatus(String tenantId) { return getTenantStatus(tenantId); }
}
